package com.ne.alice;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

/**
 * 使用SocketChannel发送文件
 */
public class NioSendClient {
    private Charset charset = Charset.forName("UTF-8");

    /**
     * 向服务器端传输文件
     */
    private void sendFile(){
        try {
            String sourcePath = "d://a.txt";
            String destPath = "a";
            File file = new File(sourcePath);
            FileChannel fileChannel = new FileInputStream(file).getChannel();
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.socket().connect(new InetSocketAddress("127.0.0.1",18899));
            socketChannel.configureBlocking(false);
            System.out.println("client成功连接服务端");
            while(!socketChannel.finishConnect()){

            }
            //发送文件名称和长度
            ByteBuffer buffer = sendFileNameAndLength(destPath, file, socketChannel);
            //发送文件内容
            int length = sendContent(file,fileChannel,socketChannel,buffer);
            if(length==-1){
                fileChannel.close();
                socketChannel.shutdownOutput();
                socketChannel.close();
            }
            System.out.println("---------文件传输完成-------------");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送文件名称和长度
     * @param destFile
     * @param file
     * @param socketChannel
     * @return
     * @throws IOException
     */
    public ByteBuffer sendFileNameAndLength(String destFile,File file,
                                            SocketChannel socketChannel) throws IOException {
        ByteBuffer fileName = charset.encode(destFile);
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        int fileNameLen = fileName.capacity();
        byteBuffer.putInt(fileNameLen);
        byteBuffer.flip();
        socketChannel.write(byteBuffer);
        byteBuffer.clear();
        System.out.println("Client 文件名称长度发送完成:"+fileNameLen);
        socketChannel.write(fileName);
        System.out.println("Client 文件名称发送完成:"+destFile);
        byteBuffer.putLong(file.length());
        byteBuffer.flip();
        socketChannel.write(byteBuffer);
        byteBuffer.clear();
        System.out.println("Client 文件长度发送完成:"+destFile);
        return byteBuffer;
    }

    /**
     * 发送文件内容
     * @param file
     * @param fileChannel
     * @param socketChannel
     * @param buffer
     * @return
     * @throws IOException
     */
    public int sendContent(File file,FileChannel fileChannel,
                           SocketChannel socketChannel,
                           ByteBuffer buffer) throws IOException {
        System.out.println("开始传输文件");
        int length = 0;
        long progress = 0;
        while((length = fileChannel.read(buffer))>0){
            buffer.flip();
            socketChannel.write(buffer);
            buffer.clear();
            progress+=length;
            System.out.println("| "+(100*progress/file.length())+"% |");
        }
        return length;
    }

    public static void main(String[] args) {
        NioSendClient nioSendClient = new NioSendClient();
        nioSendClient.sendFile();
    }
}
